import React, { useState, useEffect, useMemo } from 'react';
import { Book, Cross, Info, Mail, Menu, Phone, X, Search, ChevronRight, Star, ChevronLeft, Loader, ShoppingCart, Trash2, Send, Facebook, MessageCircle, FileText, ShieldCheck, Heart } from 'lucide-react';
// ==============================================================================
// ⚙️ ZONE DE CONFIGURATION
// ==============================================================================
// Logo par défaut (utilisé pour le loader avant que le CMS ne charge)
const DEFAULT_LOGO = "https://i.postimg.cc/7ZryvYzZ/logo.png";
// 1. LIEN CSV "INVENTAIRE"
const LIEN_PRODUITS = "https://docs.google.com/spreadsheets/d/e/2PACX-1vTITtf_EgK3nylvhoxpEF_jMuQU5fIaabj3t9iKb_7TTd8OyD2DOVPbQEHAXlbHfpr3ik2aa42OspPp/pub?output=csv";
// 2. LIEN CSV "CONTENU"
const LIEN_CONTENU = "https://docs.google.com/spreadsheets/d/e/2PACX-1vTITtf_EgK3nylvhoxpEF_jMuQU5fIaabj3t9iKb_7TTd8OyD2DOVPbQEHAXlbHfpr3ik2aa42OspPp/pub?gid=1846052469&single=true&output=csv";
// ==============================================================================
// --- UTILITAIRES ---
const parseCSV = (str) => {
const arr = [];
let quote = false;
let col = 0, row = 0;
for (let c = 0; c < str.length; c++) {
let cc = str[c], nc = str[c+1];
arr[row] = arr[row] || [];
arr[row][col] = arr[row][col] || '';
if (cc === '"' && quote && nc === '"') { arr[row][col] += cc; ++c; continue; }
if (cc === '"') { quote = !quote; continue; }
if (cc === ',' && !quote) { ++col; continue; }
if (cc === '\r' && nc === '\n' && !quote) { ++row; col = 0; ++c; continue; }
if (cc === '\n' && !quote) { ++row; col = 0; continue; }
if (cc === '\r' && !quote) { ++row; col = 0; continue; }
arr[row][col] += cc;
}
return arr;
};
const parsePrice = (priceStr) => {
if (!priceStr) return 0;
const clean = priceStr.replace(/[^\d.,]/g, '').replace(',', '.');
return parseFloat(clean) || 0;
};
// --- ICONS SVG ---
const HolyDoveIcon = ({ className }) => ( );
const SealIcon = ({ className }) => ( );
// --- COMPOSANTS UI ---
const BrandLogo = ({ url, className = "w-12 h-12", circle = false }) => {
const [imageError, setImageError] = useState(false);
const finalUrl = url || DEFAULT_LOGO;
if (finalUrl && !imageError) {
if (circle) return (
setImageError(true)} />
);
return ( setImageError(true)} />);
}
return (
);
};
const ItemVisual = ({ item }) => {
if (item.image_url && item.image_url.trim() !== "" && item.image_url.startsWith('http')) {
return ( {e.target.onerror = null; e.target.style.display = 'none'; e.target.parentElement.innerHTML = '
Image non disponible
';}} />
);
}
if (item.type === 'book') {
let bookColor = "text-red-800"; let accentColor = "bg-red-800";
if (item.name.includes("Vol. 2") || item.name.includes("Bleu")) { bookColor = "text-blue-800"; accentColor = "bg-blue-800"; }
else if (item.name.includes("Vol. 5") || item.name.includes("Or")) { bookColor = "text-yellow-700"; accentColor = "bg-yellow-600"; }
return (
Livre de la Vérité
Second Avènement
);
}
if (item.type === 'cross' || item.type === 'cross_stand') return ({item.type === 'cross_stand' &&
}
);
if (item.type === 'medal_silver' || item.type === 'medal_gold') { const isGold = item.type === 'medal_gold'; return (); }
if (item.type === 'scapular') return ();
return ();
};
const RecommendationsCarousel = ({ items, onSelect }) => {
const [currentIndex, setCurrentIndex] = useState(0);
const [visibleItems, setVisibleItems] = useState(1);
const carouselItems = items || [];
const itemCount = carouselItems.length;
// Calcul du nombre d'éléments visibles selon la taille de l'écran
useEffect(() => {
const handleResize = () => {
if (window.innerWidth >= 1280) setVisibleItems(4); // Large Screens
else if (window.innerWidth >= 1024) setVisibleItems(3); // Desktop
else if (window.innerWidth >= 768) setVisibleItems(2); // Tablet
else setVisibleItems(1); // Mobile
};
// Initial call
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
// Max index possible avant de montrer du vide
const maxIndex = Math.max(0, itemCount - visibleItems);
// Auto-scroll
useEffect(() => {
if (itemCount === 0) return;
const timer = setInterval(() => {
setCurrentIndex((prev) => prev >= maxIndex ? 0 : prev + 1);
}, 4000);
return () => clearInterval(timer);
}, [itemCount, visibleItems, maxIndex]);
const nextSlide = () => { setCurrentIndex((p) => p >= maxIndex ? 0 : p + 1); };
const prevSlide = () => { setCurrentIndex((p) => p === 0 ? maxIndex : p - 1); };
if (itemCount === 0) return null;
return (
Nos Recommandations
{/* BANDE DE DÉFILEMENT RESPONSIVE */}
{carouselItems.map((item) => (
onSelect(item)} className="bg-white p-6 rounded-xl shadow-xl border border-stone-100 flex flex-col items-center cursor-pointer transform hover:scale-105 transition-all duration-300 w-full relative overflow-hidden group h-full justify-between">
{item.name}
{item.price}
Recommandé
))}
{/* Indicateurs simples */}
{/* On affiche des points pour chaque "page" possible, pas chaque item, pour éviter la surcharge */}
{Array.from({ length: Math.ceil(itemCount / visibleItems) }).map((_, idx) => (
))}
);
};
// --- APP PRINCIPALE ---
export default function App() {
const [currentPage, setCurrentPage] = useState("home");
const [selectedItem, setSelectedItem] = useState(null);
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [isCartOpen, setIsCartOpen] = useState(false);
const [showOrderSuccess, setShowOrderSuccess] = useState(false);
const [searchQuery, setSearchQuery] = useState("");
const [inventory, setInventory] = useState([]);
const [content, setContent] = useState({});
const [loading, setLoading] = useState(true);
const [cart, setCart] = useState([]);
// Default content
const defaultContent = {
brand_logo: DEFAULT_LOGO,
hero_title: "Vérité & Rédemption",
hero_badge: "Sceau du Dieu Vivant",
hero_subtitle: "Priez pour le Sceau du Dieu Vivant et gardez-le près de vous.",
hero_citation: "- Message du Livre de la Vérité",
contact_email: "contact@lacolombe.com",
cart_payment_info: "Le paiement se fera par virement ou chèque après validation.",
about_title: "Notre Mission",
about_text: "Diffusion des messages sacrés.",
legal_mentions: "Association La Colombe.",
privacy_policy: "Données confidentielles.",
btn_books: "Livres",
btn_objects: "Objets"
};
useEffect(() => {
// 1. TITRES DYNAMIQUES
const pageTitle = currentPage === "home" ? "Accueil" :
currentPage === "books" ? "Livres" :
currentPage === "objects" ? "Objets" :
currentPage === "about" ? "À Propos" : "Contact";
document.title = `La Colombe - ${pageTitle}`;
const params = new URLSearchParams(window.location.search);
if (params.get('success') === 'true') {
setShowOrderSuccess(true);
setCart([]);
window.history.replaceState({}, document.title, "/");
}
if (LIEN_PRODUITS.includes("xxxxxxxxxxxx")) {
setLoading(false);
setContent(defaultContent);
return;
}
const fetchAllData = async () => {
try {
const prodRes = await fetch(LIEN_PRODUITS);
if (!prodRes.ok) throw new Error("Erreur produits");
const prodRaw = parseCSV(await prodRes.text());
const headers = prodRaw[0].map(h => h.trim());
const cleanInventory = prodRaw.slice(1)
.filter(row => row.length === headers.length && row[1])
.map(row => {
let obj = {};
headers.forEach((h, i) => { obj[h] = row[i] ? row[i].trim() : ""; });
return {
...obj,
id: obj.id || Math.random().toString(36).substr(2, 9),
isRecommended: obj.recommanded && (obj.recommanded.toUpperCase() === 'TRUE' || obj.recommanded.toUpperCase() === 'VRAI' || obj.recommanded === '1'),
stock: obj.stock !== undefined && obj.stock !== "" ? parseInt(obj.stock) : 1
};
});
setInventory(cleanInventory);
let loadedContent = { ...defaultContent };
if (LIEN_CONTENU && !LIEN_CONTENU.includes("xxxxxxxxxxxx")) {
try {
const contRes = await fetch(LIEN_CONTENU);
if (contRes.ok) {
const contRaw = parseCSV(await contRes.text());
contRaw.slice(1).forEach(row => {
if (row[0] && row[1]) {
loadedContent[row[0].trim()] = row[1].trim();
}
});
}
} catch (e) {
console.warn("Content load failed");
}
}
setContent(loadedContent);
setLoading(false);
} catch (err) {
console.error(err);
setLoading(false);
setContent(defaultContent);
}
};
fetchAllData();
}, [currentPage]);
const addToCart = (item) => {
setCart([...cart, item]);
setSelectedItem(null);
setIsCartOpen(true);
};
const removeFromCart = (index) => {
setCart(cart.filter((_, i) => i !== index));
};
const cartTotal = useMemo(() => cart.reduce((total, item) => total + parsePrice(item.price), 0).toFixed(2), [cart]);
const orderDetails = cart.map(item => `- ${item.name} (${item.price})`).join('\n');
const fullOrderMessage = `COMMANDE :\n${orderDetails}\n\nTOTAL ESTIMÉ : ${cartTotal}€`;
const toggleMenu = () => setIsMenuOpen(!isMenuOpen);
const getFilteredItems = () => {
let items = [];
if (currentPage === "books") items = inventory.filter(i => i.category === "Livres");
if (currentPage === "objects") items = inventory.filter(i => i.category === "Objets");
if (searchQuery.trim() !== "") {
items = items.filter(i => i.name.toLowerCase().includes(searchQuery.toLowerCase()));
}
return items;
};
const recommendedItems = inventory.filter(item => item.isRecommended);
if (loading) return (
LA COLOMBE
Chargement de la collection...
);
return (
{/* NAVBAR */}
setCurrentPage("home")}>
La Colombe
Articles Religieux
{["home", "books", "objects", "about"].map((page) => (
setCurrentPage(page)} className={`font-medium transition-all duration-300 relative py-2 ${currentPage===page ? "text-amber-800 font-bold" : "text-stone-600 hover:text-amber-700"}`}>
{page === "home" ? "Accueil" : page === "books" ? "Livres" : page === "objects" ? "Objets" : "À propos"}
{currentPage === page && }
))}
setIsCartOpen(true)} className="relative p-2 text-stone-600 hover:text-amber-700 transition-colors">
{cart.length > 0 && {cart.length} }
setCurrentPage("contact")} className="px-5 py-2 bg-gradient-to-r from-amber-700 to-amber-800 text-white rounded shadow hover:shadow-lg transition-all transform hover:-translate-y-0.5 font-medium border border-amber-900">Contact
setIsCartOpen(true)} className="relative p-2 text-stone-600">
{cart.length > 0 && {cart.length} }
{isMenuOpen && (
{setCurrentPage("home");setIsMenuOpen(false)}} className="text-left font-medium p-2 hover:bg-stone-50 rounded">Accueil
{setCurrentPage("books");setIsMenuOpen(false)}} className="text-left font-medium p-2 hover:bg-stone-50 rounded">Livres
{setCurrentPage("objects");setIsMenuOpen(false)}} className="text-left font-medium p-2 hover:bg-stone-50 rounded">Objets
{setCurrentPage("about");setIsMenuOpen(false)}} className="text-left font-medium p-2 hover:bg-stone-50 rounded">À propos
{setCurrentPage("contact");setIsMenuOpen(false)}} className="text-left font-bold text-amber-700 p-2 hover:bg-amber-50 rounded">Contact
)}
{/* CONTENU */}
{/* === HOME === */}
{currentPage === "home" && (
<>
{/* SECTION RECOMMANDATIONS (DÉPLACÉE AU-DESSUS DES TÉMOIGNAGES) */}
{inventory.length === 0 && Connexion à la base de données...
}
{recommendedItems.length > 0 && }
{/* SECTION TÉMOIGNAGES (DÉPLACÉE EN-DESSOUS) */}
{content.testi_1_text && (
Témoignages
"
{content.testi_1_text}
- {content.testi_1_author}
{content.testi_2_text && (
"
{content.testi_2_text}
- {content.testi_2_author}
)}
)}
>
)}
{/* ... (Reste du code inchangé pour les autres pages) ... */}
{/* === CATALOGUE === */}
{(currentPage === "books" || currentPage === "objects") && (
{currentPage === "books" ? : }
{currentPage === "books" ? "La Librairie" : "Objets de Piété"}
Collection Officielle
setSearchQuery(e.target.value)}
className="w-full pl-10 pr-4 py-2 border border-stone-300 rounded-full focus:ring-2 focus:ring-amber-500 focus:outline-none"
/>
{getFilteredItems().map((item) => (
setSelectedItem(item)} className={`group bg-white rounded-xl shadow-sm hover:shadow-2xl border border-stone-100 cursor-pointer overflow-hidden flex flex-col transition-all duration-500 hover:-translate-y-2 ${item.stock === 0 ? 'opacity-70 grayscale' : ''}`}>
{item.isRecommended && (
POPULAIRE
)}
{item.stock === 0 &&
Épuisé
}
{item.category}
{item.name}
{item.price} Voir Détail
))}
{getFilteredItems().length === 0 && Aucun article trouvé.
}
)}
{/* === ABOUT, LEGAL, PRIVACY PAGES === */}
{(currentPage === "about" || currentPage === "legal" || currentPage === "privacy") && (
{currentPage === "about" ? content.about_title : currentPage === "legal" ? "Mentions Légales" : "Politique de Confidentialité"}
{currentPage === "about" ? content.about_text : currentPage === "legal" ? content.legal_mentions : content.privacy_policy}
)}
{/* === CONTACT FORM === */}
{currentPage === "contact" && (
)}
{/* --- MODAL DÉTAIL ARTICLE --- */}
{selectedItem && (
setSelectedItem(null)}>
e.stopPropagation()}>
setSelectedItem(null)} className="absolute top-4 right-4 z-10 p-2 bg-white/80 rounded-full hover:bg-red-50 hover:text-red-600 transition-colors shadow-sm">
{selectedItem.category}
{selectedItem.name}
{selectedItem.price}
{selectedItem.description}
{selectedItem.stock > 0 ? (
addToCart(selectedItem)} className="w-full py-4 bg-stone-900 text-white rounded hover:bg-stone-800 font-bold transition-all shadow-lg flex justify-center items-center gap-2 uppercase tracking-wide text-sm">
Ajouter au panier
) : (
Rupture de stock
)}
)}
{/* --- MODAL PANIER --- */}
{isCartOpen && (
setIsCartOpen(false)}>
e.stopPropagation()}>
Mon Panier
setIsCartOpen(false)} className="p-2 hover:bg-stone-100 rounded-full">
{cart.length === 0 ? (
Votre panier est vide.
setIsCartOpen(false)} className="mt-4 text-amber-700 font-bold hover:underline">Retourner à la boutique
) : (
<>
{cart.map((item, idx) => (
removeFromCart(idx)} className="text-stone-400 hover:text-red-500">
))}
Total estimé {cartTotal} €
>
)}
)}
{/* --- MODAL SUCCÈS COMMANDE --- */}
{showOrderSuccess && (
setShowOrderSuccess(false)}>
e.stopPropagation()}>
Merci !
Votre demande a bien été envoyée. Nous vous recontacterons très vite pour le paiement.
setShowOrderSuccess(false)} className="bg-amber-700 text-white px-6 py-2 rounded font-bold hover:bg-amber-800">Fermer
)}
{/* FOOTER */}
);
}